using System;
using System.IO;
using System.Xml.Linq;
using Engine;
using GameEntitySystem;
using TemplatesDatabase;
using XmlUtilities;

namespace Game
{
	public static class LJGameManager
	{
		private const string clientWorldDir = "data:/ClientWorld";

		public static string PrepareClientWorld(Project project)
		{
			DeleteClientWorld();
			ValuesDictionary valuesDictionary = new ValuesDictionary();
			ReflectionUtils.InvokeMethod((object)project.FindSubsystem<SubsystemGameInfo>(), "Save", new object[1] { valuesDictionary });
			valuesDictionary.SetValue("WorldDirectoryName", "data:/ClientWorld");
			XElement xElement = ModUtils.CreateProject("LJProject", valuesDictionary);
			XElement elem = xElement.Element("Subsystems");
			SaveSubsystem(elem, project.FindSubsystem<SubsystemPlayers>(true));
			SaveSubsystem(elem, project.FindSubsystem<SubsystemRemotePlayers>(true));
			SaveSubsystem(elem, project.FindSubsystem<SubsystemRemoteEntities>(true));
			SaveSubsystem(elem, project.FindSubsystem<SubsystemTimeOfDay>(true));
			XElement xElement2 = new XElement("Entities");
			xElement.Add(xElement2);
			EntityDataList entityDataList = project.SaveEntities(project.Entities);
			GameDatabase gameDatabase = DatabaseManager.GameDatabase;
			DatabaseObject databaseObject = gameDatabase.Database.FindDatabaseObject("Player", gameDatabase.EntityTemplateType, true);
			foreach (EntityData entitiesDatum in entityDataList.EntitiesData)
			{
				if (entitiesDatum.ValuesDictionary.DatabaseObject.EffectivelyInheritsFrom(databaseObject))
				{
					XElement xElement3 = new XElement("Entity");
					entitiesDatum.Save(xElement3);
					xElement2.Add(xElement3);
				}
			}
			Storage.CreateDirectory("data:/ClientWorld");
			using (Stream stream = Storage.OpenFile(Storage.CombinePaths("data:/ClientWorld", "Project.xml"), OpenFileMode.Create))
			{
				XmlUtils.SaveXmlToStream(xElement, stream, null, true);
			}
			return "data:/ClientWorld";
		}

		public static WorldInfo GetClientWorldInfo()
		{
			return WorldsManager.GetWorldInfo("data:/ClientWorld");
		}

		public static void ExportClientWorld(Stream s)
		{
			if (Storage.DirectoryExists("data:/ClientWorld"))
			{
				WorldsManager.ExportWorld("data:/ClientWorld", s);
			}
		}

		public static string ImportClientWorld(Stream s)
		{
			DeleteClientWorld();
			Storage.CreateDirectory("data:/ClientWorld");
			ReflectionUtils.InvokeStaticMethod(typeof(WorldsManager), "UnpackWorld", new object[3] { "data:/ClientWorld", s, true });
			return "data:/ClientWorld";
		}

		public static void DisableUpdatables(Project project)
		{
			SubsystemUpdate subsystemUpdate = project.FindSubsystem<SubsystemUpdate>(true);
			subsystemUpdate.RemoveUpdateable(project.FindSubsystem<SubsystemCreatureSpawn>());
			subsystemUpdate.RemoveUpdateable(project.FindSubsystem<SubsystemSpawn>());
			foreach (Entity entity in project.Entities)
			{
				EntityAdded(project, new EntityAddRemoveEventArgs(entity));
			}
			project.EntityAdded += new EventHandler<EntityAddRemoveEventArgs>(EntityAdded);
		}

		private static void EntityAdded(object sender, EntityAddRemoveEventArgs e)
		{
			Project project = sender as Project;
			SubsystemPlayers subsystemPlayers = project.FindSubsystem<SubsystemPlayers>(true);
			SubsystemRemotePlayers subsystemRemotePlayers = project.FindSubsystem<SubsystemRemotePlayers>(true);
			if (subsystemPlayers.IsPlayer(e.Entity) && subsystemRemotePlayers.IsMainPlayer(e.Entity.FindComponent<ComponentPlayer>(true).PlayerData))
			{
				return;
			}
			SubsystemUpdate subsystemUpdate = project.FindSubsystem<SubsystemUpdate>(true);
			foreach (Component component in e.Entity.Components)
			{
				IUpdateable updateable = component as IUpdateable;
				if (updateable != null && component is ComponentBehavior)
				{
					subsystemUpdate.RemoveUpdateable(updateable);
				}
			}
		}

		private static void DeleteClientWorld()
		{
			if (Storage.DirectoryExists("data:/ClientWorld"))
			{
				WorldsManager.DeleteWorld("data:/ClientWorld");
			}
		}

		private static void SaveSubsystem(XElement elem, Subsystem subsystem)
		{
			XElement xElement = new XElement("Values");
			XmlUtils.SetAttributeValue(xElement, "Name", subsystem.ValuesDictionary.DatabaseObject.Name);
			ValuesDictionary valuesDictionary = new ValuesDictionary();
			ReflectionUtils.InvokeMethod((object)subsystem, "Save", new object[1] { valuesDictionary });
			valuesDictionary.Save(xElement);
			elem.Add(xElement);
		}
	}
}
